/// <reference path="DreamSpace.Common.ts"/>

module DreamSpace {

    /** Contains a series of core DreamSpace UI controls wrapped in GraphItem derived classes. */
    export module UI {

        // ===================================================================================================================

        /** Represents a basic text node graph item that renders plain text (no HTML). 
        * This is inline with the standard which declares that all DOM elements with text should have text nodes.
        */
        export class PlainText extends GraphItem {
            // ---------------------------------------------------------------------------------------------------------------

            static UIProperties: { Text; }
            = {
                Text: "Text"
            };

            text: (text?: string) => string = DreamSpace.GraphItem.accessor(PlainText.UIProperties.Text);

            // ---------------------------------------------------------------------------------------------------------------

            constructor(parent: GraphItem, text: string = "") {
                super(parent)
                this.text(text);
                this.htmlTag = "";
            }

            // ---------------------------------------------------------------------------------------------------------------

            createUIElement(): Node {
                this.assertSupportedElementTypes("", "Text");
                return document.createTextNode("");
            }

            // ---------------------------------------------------------------------------------------------------------------

            onRedraw(recursive: bool = true) {
                super.onRedraw(recursive);
                (<Text>this.element).textContent = this.properties[PlainText.UIProperties.Text];
            }

            // ---------------------------------------------------------------------------------------------------------------
        }

        // ===================================================================================================================

        /** Represents an HTML text node graph item that renders the content in the 'innerHTML of a DIV element. 
        */
        export class HTMLText extends GraphItem {
            // ---------------------------------------------------------------------------------------------------------------

            static UIProperties: { HTML; }
            = {
                HTML: "HTML"
            };

            html: (html?: string) => string = DreamSpace.GraphItem.accessor(HTMLText.UIProperties.HTML);

            // ---------------------------------------------------------------------------------------------------------------

            constructor(parent: GraphItem, html: string = "") {
                super(parent)
                this.html(html);
                this.htmlTag = "span";
            }

            // ---------------------------------------------------------------------------------------------------------------

            createUIElement(): Node {
                this.assertUnsupportedElementTypes("html", "head", "body", "script", "audio", "canvas", "object");
                return super.createUIElement();
            }

            // ---------------------------------------------------------------------------------------------------------------

            onRedraw(recursive: bool = true) {
                super.onRedraw(recursive);
                this.htmlElement.innerHTML = this.properties[HTMLText.UIProperties.HTML];
            }

            // ---------------------------------------------------------------------------------------------------------------
        }

        // ===================================================================================================================

        /** Represents an HTML text node graph item that renders the content in the 'innerHTML of a DIV element. 
        */
        export class Header extends GraphItem {
            // ---------------------------------------------------------------------------------------------------------------

            static UIProperties: { HTML; }
            = {
                HTML: "HTML"
            };

            html: (html?: string) => string = DreamSpace.GraphItem.accessor(Header.UIProperties.HTML);

            // ---------------------------------------------------------------------------------------------------------------

            private _HeaderType: number;

            // ---------------------------------------------------------------------------------------------------------------

            constructor(parent: GraphItem, html: string = "", headerLevel: number = 1) {
                super(parent)
                if (headerLevel < 1 || headerLevel > 6)
                    throw DreamSpace.Exception("HTML only supports header levels 1 through 6.");
                this._HeaderType = headerLevel;
                this.html(html);
            }

            // ---------------------------------------------------------------------------------------------------------------

            createUIElement(): Node {
                this.htmlTag = "h" + this._HeaderType;
                this.assertSupportedElementTypes("h1", "h2", "h3", "h4", "h5", "h6");
                return super.createUIElement();
            }

            // ---------------------------------------------------------------------------------------------------------------

            onRedraw(recursive: bool = true) {
                super.onRedraw(recursive);
                this.htmlElement.innerHTML = this.properties[Header.UIProperties.HTML];
            }

            // ---------------------------------------------------------------------------------------------------------------
        }

        // ===================================================================================================================

        /** Represents a row on a table type in Bootstrap. */
        export class TableRow extends GraphItem {

            // ---------------------------------------------------------------------------------------------------------------

            constructor(parent: GraphItem) {
                super(parent)
                this.onPropertyChanged = null;
                this.htmlTag = "tr";
            }

            // ---------------------------------------------------------------------------------------------------------------

            createUIElement(): Node {
                this.assertSupportedElementTypes("tr");
                return super.createUIElement();
            }

            // ---------------------------------------------------------------------------------------------------------------
        }

        // ===================================================================================================================
    }

    /** Contains a series of core DreamSpace communication based GraphItem derived classes. */
    export module Comm {

        // ===================================================================================================================

        /** Represents a client side data communications object. 
        * The connection URI determines the method.  If the URI starts with "ws://" or "wss://", then web sockets are assumed, otherwise AJAX communication
        * is assumed, and the URL represents a resource location.
        */
        export class DataClient extends GraphItem {

            // ---------------------------------------------------------------------------------------------------------------

            xmlHttpRequest: XMLHttpRequest = null; // (in support of AJAX)
            webSocket: WebSocket = null; // (in support of web sockets)

            connectionURI: string = null;
            /** The method for getting data when using XMLHttpRequest (AJAX) connections (i.e. 'GET', 'POST', 'PUT', or 'DELETE'); The default is 'get'. */
            xmlHttpMethod: string = "get";

            /** A username for XMLHttpRequest (AJAX) connections, if applicable. */
            userName: string = null;
            /** A password for XMLHttpRequest (AJAX) connections, if applicable. */
            password: string = null;

            onOpen: () => any;
            onError: () => any;
            onData: () => any;
            onClosed: () => any;

            // ---------------------------------------------------------------------------------------------------------------

            constructor(parent: GraphItem, connectionURI: string = null) {
                super(parent)
                this.onPropertyChanged = null;
                this.htmlTag = "tr";
                this.connectionURI = connectionURI;
            }

            // ---------------------------------------------------------------------------------------------------------------

            connect(connectionURI: string = null) {
                this.connectionURI = connectionURI || this.connectionURI;

                if (!this.connectionURI) throw DreamSpace.Exception("The 'connectionURI' value is empty or invalid.");

                // ... disconnect any current operations in progress ...
                // (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest?redirectlocale=en-US&redirectslug=DOM%2FXMLHttpRequest)
                // (https://developer.mozilla.org/en-US/docs/Web/API/WebSocket?redirectlocale=en-US&redirectslug=WebSockets%2FWebSockets_reference%2FWebSocket)

                if (this.xmlHttpRequest
                    && this.xmlHttpRequest.readyState >= 1 /*OPENED*/
                    && this.xmlHttpRequest.readyState < 4/*DONE*/)
                    this.xmlHttpRequest.abort();
                else if (this.webSocket && this.webSocket.readyState >= 0 /*CONNECTING; 1=OPENED*/
                    && this.xmlHttpRequest.readyState < 2/*CLOSING; 3=CLOSED*/)
                    this.webSocket.close(4000, "Reconnect requested.");

                var protocol = this.connectionURI.substring(0, this.connectionURI.indexOf("://")).toLowerCase();
                if (protocol == "ws" || protocol == "wss") {
                    this.webSocket = new WebSocket(this.connectionURI);
                    this.webSocket.onopen = (ev: Event) => { if (this.onOpen) this.onOpen(); };
                    this.webSocket.onerror = (ev: ErrorEvent) => { if (this.onError) this.onError(); };
                    this.webSocket.onmessage = (ev: any) => { if (this.onData) this.onData(); };
                    this.webSocket.onclose = (ev: CloseEvent) => { if (this.onClosed) this.onClosed(); };
                } else {
                    this.xmlHttpRequest = new XMLHttpRequest();
                    this.xmlHttpRequest.onerror = (ev: ErrorEvent) => { if (this.onError) this.onError(); };
                    this.xmlHttpRequest.onload= (ev: any) => {};
                    this.xmlHttpRequest.onloadstart= (ev: any) => {};
                    this.xmlHttpRequest.onloadend= (ev: ProgressEvent) => {};
                    this.xmlHttpRequest.onabort= (ev: any) => {};
                    this.xmlHttpRequest.onprogress= (ev: ProgressEvent) => {};
                    this.xmlHttpRequest.onreadystatechange= () => {};
                    this.xmlHttpRequest.ontimeout= (ev: any) => {};
                    this.xmlHttpRequest.open(this.xmlHttpMethod, this.connectionURI, true, this.userName, this.password);
                }
            }

            // ---------------------------------------------------------------------------------------------------------------
        }

        // ===================================================================================================================

    }
}
